package com.fico.blaze;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.blazesoft.engines.rules.NdClassProviderResource;
import com.blazesoft.engines.rules.xml.*;
import com.blazesoft.objects.base.NdExternalProperty;
import com.blazesoft.objects.base.NdExternalTypeDescriptor;
import com.blazesoft.repository.naming.NdLocation;
import com.blazesoft.repository.naming.NdLocationFactory;
import com.blazesoft.template.engine.NdInvalidTemplateException;
import com.blazesoft.template.engine.NdTemplateException;
import com.blazesoft.template.repository.*;
import com.blazesoft.template.repository.admin.NdPromBomAdmin;
import com.blazesoft.template.repository.objects.NdPromTemplate;
import com.blazesoft.template.repository.objects.NdPromTextContent;
import com.blazesoft.template.repository.objects.NdPromTextContentFactory;
import com.blazesoft.template.repository.objects.bom.NdPromBomConstructContentFactory;
import com.blazesoft.template.repository.objects.bom.NdPromExternalBomContent;
import com.blazesoft.template.repository.objects.group.NdPromGroupContentImpl;
import com.blazesoft.template.repository.util.NdPromProjectUtil;
import lombok.Data;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

@Data
public class AccessPromProject {
    private String projectFullPath;

    private String bomFullPath;

    private String projectName;

    private String bomName;

    private NdRomProject romProject;

    private NdPromProject promProject;

    private NdPromDirectory bomDirectory;

    private NdRomDirectory romRootDirectory;

    private NdPromBomAdmin promBomAdmin = new NdPromBomAdmin();



    public AccessPromProject(String projectFullPath, String bomFullPath) {
        this.projectFullPath = projectFullPath;
        this.bomFullPath = bomFullPath;
        projectName = projectFullPath.substring(projectFullPath.lastIndexOf("/") + 1);
        bomName = bomFullPath.substring(bomFullPath.lastIndexOf("/") + 1);

    }

    public void _initData(NdRomConnectionManager connectionManager) {
        NdRomConnectionContext connectionContext = connectionManager.getConnectionContext();
        romRootDirectory = connectionContext.getRoot();
        try {
            romProject = (NdRomProject) romRootDirectory.lookupEntry(NdLocationFactory.createLocation(projectFullPath));
            promProject = connectionContext.getProjectFactory().createProject(romProject);


        } catch (NdRomException e) {

            e.printStackTrace();
        }

    }

    /**
     * 解析xmlbom到JSONArray
     * @return
     */
    public JSONArray parseXmlBom() {
        List<String> blackList = Arrays.asList("DecisionFlowHistory", "DecisionFlowStepHistory", "MessageList", "Message", "ProcessingHistory", "RuleHistory", "RulesetHistory", "ScoredCharacteristic", "ScoreModelReturnInfo");

        JSONArray jsonArray =null;
        try {

            NdLocation bomLocation = NdLocationFactory.createLocation(bomFullPath);
            NdPromTemplate promTemplate = (NdPromTemplate) promProject.getTemplateManager().loadTemplate(bomLocation);
            NdPromGroupContentImpl content = (NdPromGroupContentImpl) promTemplate.getEntityContent();
            NdPromExternalBomContent bomContent = (NdPromExternalBomContent) content.getChildren()[0];
            NdClassProviderResource resource = bomContent.getClassProviderResource();
            NdAdvisorExternalXmlClassProvider xmlClassProvider = (NdAdvisorExternalXmlClassProvider) resource.getClassProvider();
            Enumeration enumeration = xmlClassProvider.getExternalClasses();
            jsonArray = new JSONArray();
            while (enumeration.hasMoreElements()) {
                JSONObject jsonObject = new JSONObject();
                NdAdvisorExternalXmlClass xmlClass = (NdAdvisorExternalXmlClass) enumeration.nextElement();
                if (blackList.contains(xmlClass.getName())) {
                    continue;
                }
                jsonObject.put("name", xmlClass.getName());
                JSONArray objects = new JSONArray();
                NdExternalProperty[] properties = xmlClass.getDeclaredProperties();
                //设置元素数组和属性数组
                JSONArray elementArray = new JSONArray();
                JSONArray attributeArray = new JSONArray();
                for (NdExternalProperty p : properties) {
                    JSONObject object = new JSONObject();
                    NdAdvisorExternalXmlProperty pro = (NdAdvisorExternalXmlProperty) p;
                    if (blackList.contains(pro.getImplementationPropertyName())) {
                        continue;
                    }
                    NdExternalTypeDescriptor typeDescriptor = pro.getPropertyType();
                    Method method = typeDescriptor.getClass().getDeclaredMethod("getTypeName");
                    method.setAccessible(true);
                    String type = (String) method.invoke(typeDescriptor);
                    object.put("type", type.replaceAll("schema\\.xsd\\$", ""));
                    object.put("srlName", pro.getName());
                    object.put("xmlName", pro.getImplementationPropertyName());


                    //  objects.add(object);
                    //分离出元素数组和属性数组
                    if (object.getString("type").contains("$")) {
                        elementArray.add(object);
                    } else {
                        attributeArray.add(object);
                    }
                }


                //排序
                elementArray = jsonArraySort(elementArray, "xmlName", false);
                attributeArray = jsonArraySort(attributeArray, "xmlName", false);
                int index = elementArray.size() + attributeArray.size();
                for (int i = 0; i < elementArray.size(); i++) {
                    objects.add(i, elementArray.getJSONObject(i));
                }
                for (int j = 0; j < attributeArray.size(); j++) {
                    objects.add(elementArray.size() + j, attributeArray.get(j));
                }
                jsonObject.put("properties", objects);
                jsonArray.add(jsonObject);

            }


        } catch (NdRomException e) {
            e.printStackTrace();
        } catch (NdInvalidTemplateException e) {
            e.printStackTrace();
        } catch (NdTemplateException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        jsonArray = jsonArraySort(jsonArray, "name", false);
        promProject.dispose();
        return jsonArray;
    }


    /**
     * JSONArray 字段升序排序
     * @param jsonArr
     * @param sortKey
     * @param is_desc
     * @return
     */
    public static JSONArray jsonArraySort(JSONArray jsonArr, final String sortKey, final boolean is_desc) {
        //存放排序结果json数组
        JSONArray sortedJsonArray = new JSONArray();
        //用于排序的list
        List<JSONObject> jsonValues = new ArrayList<JSONObject>();
        //将参数json数组每一项取出，放入list
        for (int i = 0; i < jsonArr.size(); i++) {
            jsonValues.add(jsonArr.getJSONObject(i));
        }
        //快速排序，重写compare方法，完成按指定字段比较，完成排序
        Collections.sort(jsonValues, new Comparator<JSONObject>() {
            //排序字段
            private final String KEY_NAME = sortKey;
            //重写compare方法

            public int compare(JSONObject a, JSONObject b) {
                String valA = new String();
                String valB = new String();
                try {
                    valA = a.getString(KEY_NAME);

                    valB = b.getString(KEY_NAME);

                } catch (JSONException e) {
                    e.printStackTrace();
                }
                //是升序还是降序
                if (is_desc) {
                    return -valA.compareTo(valB);
                } else {
                    return -valB.compareTo(valA);
                }

            }
        });

        //将排序后结果放入结果jsonArray
        for (int i = 0; i < jsonArr.size(); i++) {

            sortedJsonArray.add(jsonValues.get(i));
        }

        return sortedJsonArray;
    }

    /**
     * bom生成xsd
     * @param xsdPath
     * @param jsonArray
     */
    public void BomToXsdAndWriteMap(String xsdPath,JSONArray jsonArray,String mapFilePath){
        XsdTemplate xsdTemplate = new XsdTemplate();
        try {
            xsdTemplate.writeXsd(xsdPath,jsonArray);
            writeMapToFile(mapFilePath,xsdTemplate.getEnToCnMap());
        } catch (IOException e) {

            e.printStackTrace();
        }
    }

    /**
     * Xsd 生成BOM
     * @param xsdPath
     */
    public void XsdToBom(String xsdPath){
        try {
            String absolution_bom = bomFullPath.substring(0, bomFullPath.lastIndexOf("/"));
            promProject.removeDirectory(NdLocationFactory.createLocation(absolution_bom));
            bomDirectory = promProject.addDirectory(NdLocationFactory.createLocation(absolution_bom));
         //   bomDirectory = (NdPromDirectory) promProject.lookupEntry(NdLocationFactory.createLocation(absolution_bom));
            NdPromExternalBomContent bomContent = NdPromBomConstructContentFactory.newExternalBomContent((NdPromRulesProject) promProject, 24);
            //bom实例名称
            NdPromTextContent pc = NdPromTextContentFactory.newTextContent(bomName);
            //设置bom名称
            bomContent.setNameContent(pc);
            //new bom信息实例
            NdXmlClassMappingInfo newBomMappingInfo = new NdXmlClassMappingInfo();
            //设置xsd
            newBomMappingInfo.setXmlSchema(new String[]{xsdPath});
            //添加bom信息
            promBomAdmin.addImportedClasses(bomContent, newBomMappingInfo);

            //保存bom
            NdPromItemContent itemContent = (NdPromItemContent) bomContent;
            NdPromItem promItem = NdPromProjectUtil.newItem(itemContent, promProject);
            bomDirectory.addItem(promItem);
            promItem.save();
        } catch (NdRomException e) {

            e.printStackTrace();
        }
    }


    /**
     * 中英文映射文件生成
     * @param EntoCnPath
     * @param map
     */
    public void writeMapToFile(String EntoCnPath,Map<String,String> map) {
            File file = new File(EntoCnPath);
            try {
                FileWriter fileWriter = new FileWriter(file);

                for (Map.Entry<String, String> entry : map.entrySet()) {
                    fileWriter.write(entry.getKey()+"="+entry.getValue()+"\n");

                }
                fileWriter.flush();
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }


        }

        public void mapChinese(String EnToCnPath){
            NdLocation bomLocation = NdLocationFactory.createLocation(bomFullPath);
            try {
                NdPromExternalBomContent bomContent = (NdPromExternalBomContent) promBomAdmin.getPromBomContent(promProject, bomLocation);
                NdClassProviderResource classProviderResource = bomContent.getClassProviderResource();
                NdAdvisorExternalXmlClassProvider advisorExternalXmlClassProvider = (NdAdvisorExternalXmlClassProvider) classProviderResource.getClassProvider();
                File file = new File(EnToCnPath);
                Properties properties = new Properties();
                properties.load(new FileInputStream(file));
                Set<String> strings = properties.stringPropertyNames();
                for (String s : strings) {
                    String[] temp = s.split("\\.");
                    String xmlClass = temp[0];
                    String xmlProperties = temp[1];
                    String srlName = properties.getProperty(s);
                    srlName =new String(srlName.getBytes("ISO-8859-1"), "utf-8");
                    System.out.println(srlName);
                    NdAdvisorExternalXmlClass advisorExternalXmlClass = (NdAdvisorExternalXmlClass) advisorExternalXmlClassProvider.findExternalClass(xmlClass);
                    bANUBjuS custom = advisorExternalXmlClassProvider.getCustomClassInfo(advisorExternalXmlClass);
                    if (custom == null) {
                        custom = new bANUBjuS(advisorExternalXmlClass);
                    }
                    NdAdvisorExternalXmlProperty advisorExternalXmlProperty = (NdAdvisorExternalXmlProperty) advisorExternalXmlClass.lookupProperty(xmlProperties);
                    NdExternalXmlPropertyCustomInfo externalXmlPropertyCustomInfo = custom.bANUBjoM(advisorExternalXmlProperty);
                    if (externalXmlPropertyCustomInfo == null) {
                        externalXmlPropertyCustomInfo = new NdExternalXmlPropertyCustomInfo(advisorExternalXmlProperty);
                    }
                    externalXmlPropertyCustomInfo.bANUEijA(srlName);
                    custom.bANUBjpN(externalXmlPropertyCustomInfo);
                    advisorExternalXmlClassProvider.addCustomClassInfo(custom);

                }


                bomContent.setClassProviderResource(classProviderResource);
                NdPromItemContent itemContent = (NdPromItemContent) bomContent;
                itemContent.getItem().save();
                promProject.save();
                //释放资源
                promProject.dispose();

            } catch (NdRomException e) {

                e.printStackTrace();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }


        }

}
